<?php
defined('BASEPATH') OR exit('No direct script access allowed');

class Wechat {

	//微信参数
	private $appid = APPID;
	private $appsecret = APPSECRET;
    private $payMerchantId = WX_PAY_MERCHANTId;
    private $payKey = WX_PAY_KEY;

    private $qyAppid = QYWX_APPID;
	private $qyAppsecret = QYWX_SECRET;

    public function __construct(){
        $this->CI= &get_instance();
	}

    public function aa() {
        // $this->CI->library('session');
        var_export($this->CI->session->userdata('wx')['']);exit;
    }

    // 微信开发者接入
    public function auth(){
        $signature = $_GET['signature'];
        $timestamp = $_GET['timestamp'];
        $nonce = $_GET['nonce'];
        $token = "ygbaobao";
        
        $tmpArr = array($token, $timestamp, $nonce);
        sort($tmpArr, SORT_STRING);
        $tmpStr = implode($tmpArr);
        $tmpStr = sha1($tmpStr);

        if($tmpStr == $signature ){
            exit($_GET['echostr']);
        }else{
            exit;
        }
    }

	// 获取accessToken
	public function get_access_token(){
        $this->CI->load->model('configModel');
        $tokenName = "access_token_". $this->appid;
        // 获取rmx_sys_config表的access_token
        $arr = $this->CI->configModel->get_config_info($tokenName, false);
        // 检查有效时间
        if(!empty($arr) && strtotime($arr['createtime']) + 6000 > time()) {
            // 有效就返回该token
            return $arr['config_value'];
        }
		//请求服务器
		$url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={$this->appid}&secret={$this->appsecret}";
    	$result = json_decode(file_get_contents($url), true);
    	//抛错
    	if(isset($result['errcode'])) throw new Exception($result['errmsg']);
    	// 回写配置
        $this->CI->configModel->set_config_value($tokenName, $result['access_token']);
    	return $result['access_token'];
	}

	// 获取jsapi_ticket
    public function get_jsapi_ticket(){
    	$accessToken = $this->get_access_token($this->appid, $this->appsecret);
    	// 检查有效时间
        $ticketName = "jsapi_ticket_". $this->appid;
        // 获取rmx_sys_config表的ticket
        $arr = $this->CI->configModel->get_config_info($ticketName, false);
        // 检查有效时间
        if(!empty($arr) && strtotime($arr['createtime']) + 6000 > time()) {
            // 有效就返回该token
            return $arr['config_value'];
        }
        // 请求服务器
    	$url = "https://api.weixin.qq.com/cgi-bin/ticket/getticket?access_token={$accessToken}&type=jsapi";
        $result = json_decode(file_get_contents($url), true);
        if(ENV != 'local') {
            // 本地不校验
            //抛错
            if($result['errmsg'] != 'ok') throw new Exception($result['errmsg']);
        }

    	// 回写配置
        $this->CI->configModel->set_config_value($ticketName, $result['ticket']);
    	return $result['ticket'];
    }

	// 获取accessToken（企业微信）
	public function get_qy_access_token(){
        $this->CI->load->model('configModel');
        $tokenName = "qy_access_token_". $this->qyAppid;
        // 获取rmx_sys_config表的access_token
        $arr = $this->CI->configModel->get_config_info($tokenName, false);
        // 检查有效时间
        if(!empty($arr) && strtotime($arr['createtime']) + 6000 > time()) {
            // 有效就返回该token
            return $arr['config_value'];
        }
		//请求服务器
		$url = "https://qyapi.weixin.qq.com/cgi-bin/gettoken?corpid={$this->qyAppid}&corpsecret={$this->qyAppsecret}";
    	$result = json_decode(file_get_contents($url), true);
    	//抛错
    	if(isset($result['errcode']) && $result['errcode'] != 0) throw new Exception($result['errmsg']);
    	// 回写配置
        $this->CI->configModel->set_config_value($tokenName, $result['access_token']);
    	return $result['access_token'];
	}

	// 获取jsapi_ticket（企业微信）
    public function get_qy_jsapi_ticket(){
    	$accessToken = $this->get_qy_access_token($this->qyAppid, $this->qyAppsecret);
    	// 检查有效时间
        $ticketName = "qy_jsapi_ticket_". $this->qyAppid;
        // 获取rmx_sys_config表的ticket
        $arr = $this->CI->configModel->get_config_info($ticketName, false);
        // 检查有效时间
        if(!empty($arr) && strtotime($arr['createtime']) + 6000 > time()) {
            // 有效就返回该token
            return $arr['config_value'];
        }
        // 请求服务器
    	$url = "https://qyapi.weixin.qq.com/cgi-bin/get_jsapi_ticket?access_token={$accessToken}&type=jsapi";
        $result = json_decode(file_get_contents($url), true);

        if(ENV != 'local') {
            // 本地不校验
            //抛错
            if($result['errmsg'] != 'ok') throw new Exception($result['errmsg']);
        }

    	// 回写配置
        $this->CI->configModel->set_config_value($ticketName, $result['ticket']);
    	return $result['ticket'];
    }

    // 获取jssdk签名参数
    public function jssdk_data($url){
    	$data['noncestr'] = random_str(12);

        // 判断企业微信
        if(!isset($this->CI->session->userdata('wx')['qywx'])) {
            $data['jsapi_ticket'] = $this->get_jsapi_ticket();
        } else {
            $data['jsapi_ticket'] = $this->get_qy_jsapi_ticket();
        }

    	$data['timestamp'] = time();
    	$data['url'] = $url;
        $tdata = $data;
        foreach($tdata as $k => $v) {
            $tdata[$k] = $k. "=". $v;
        }
    	sort($tdata);
    	$data['signature'] = sha1(implode("&", $tdata));
        
        // 判断企业微信
        if(!isset($this->CI->session->userdata('wx')['qywx'])) {
            $data['appid'] = $this->appid;
        } else {
            $data['appid'] = $this->qyAppid;
        }

    	return $data;
    }
    // 网页授权获取openid，无需获取用户信息
    public function authorize() {
        if(ENV == 'local') {
            // header("Location:" . site_url($_SERVER['REQUEST_URI']));
            // $sessArr = array('openid' => 'oHUUKw1IpoMHGknGlDdWzFoSd060');
            $sessArr = array('openid' => 'oHUUKw1IpoMHGknGlDdWzFoSd060');
            $this->CI->session->set_userdata('wx', $sessArr);
            header('http://192.168.1.111/wx/');
            exit;
        }
        $code = isset($_GET['code']) ? $_GET['code'] : '';
        if($code) {
            $url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid={$this->appid}&secret={$this->appsecret}&code={$code}&grant_type=authorization_code";
            $result = json_decode(file_get_contents($url), true);
            if(isset($result['openid'])) {
                // session设置openid
                if(empty($this->CI->session->userdata('wx'))) {
                    $sessArr = array('openid' => $result['openid']);
                } else {
                    $sessArr = array_merge($this->CI->session->userdata('wx'), array('openid' => $result['openid']));
                }
                $this->CI->session->set_userdata('wx', $sessArr);
                // 返回原来的页面
                header("Location:" . site_url($_SERVER['REQUEST_URI']));
                exit;
            } else {
                print_r($result);
                exit;
            }
        } else {
            // 重定向回原来页面
            $target = site_url($_SERVER['REQUEST_URI']);
            // 重定向支持多个查询参数，不然只取第一个
            $target = str_replace('&', '%26', $target);
            // $url = "https://open.weixin.qq.com/connect/oauth2/authorize?appid={$this->appid}&redirect_uri={$target}&response_type=code&scope=snsapi_userinfo#wechat_redirect";

            $url = "https://open.weixin.qq.com/connect/oauth2/authorize?appid={$this->appid}&redirect_uri={$target}&response_type=code&scope=snsapi_userinfo&connect_redirect=1#wechat_redirect";

            header("Location:" . $url);
            exit;
        }
        
    }

    // 获取用户基本信息
    public function get_user_info($openid){
        $accessToken = $this->get_access_token($this->appid, $this->appsecret);
        $url = "https://api.weixin.qq.com/cgi-bin/user/info?access_token={$accessToken}&openid={$openid}";
        $result = json_decode(file_get_contents($url), true);
        // echo '<pre>';var_export(($result));exit;
    	//抛错
        // if(isset($result['errcode'])) throw new Exception('服务器错误：' . $result['errmsg']);
        if(isset($result['errcode'])) {
            return array();
        }
        return $result;
    }

    // 网页授权获取用户信息，未关注也可以获取
    public function get_wxInfo(){
    	if(isset($_SESSION['wxInfo']) && isset($_SESSION['wxInfo']['appid']) && $_SESSION['wxInfo']['appid'] == $this->appid) return $_SESSION['wxInfo'];

        $code = isset($_GET['code']) ? $_GET['code'] : '';
        if($code) {
            $url = "https://api.weixin.qq.com/sns/oauth2/access_token?appid={$this->appid}&secret={$this->appsecret}&code={$code}&grant_type=authorization_code";
            $result = json_decode(file_get_contents($url), true);
            if(isset($result['openid'])) {
                //获取用户信息
                $url = "https://api.weixin.qq.com/sns/userinfo?access_token={$result['access_token']}&openid={$result['openid']}&lang=zh_CN";
                $result = json_decode(file_get_contents($url), true);

                //添加到session
                $result['appid'] = $this->appid;
                $_SESSION['wxInfo'] = $result;
                return $result;
            } else {
                print_r($result);
                exit;
            }
        } else {
            // $target = urlencode(get_url());
            $target = 'http://mytest.com/wx/home';
            $url = "https://open.weixin.qq.com/connect/oauth2/authorize?appid={$this->appid}&redirect_uri={$target}&response_type=code&scope=snsapi_userinfo#wechat_redirect";
            header("Location:". $url);
            exit;
        }
    }

    // 下载jssdk上传的图片
    public function download_media($mediaId){
        // 判断企业微信
        if(!isset($this->CI->session->userdata('wx')['qywx'])) {
            $accessToken = $this->get_access_token($this->appid, $this->appsecret);
        } else {
            $accessToken = $this->get_qy_access_token($this->qyAppid, $this->qyAppsecret);
        }

        // http://file.api.weixin.qq.com停用
        // $url = "http://file.api.weixin.qq.com/cgi-bin/media/get?access_token={$accessToken}&media_id={$mediaId}";
        // 判断企业微信
        if(!isset($this->CI->session->userdata('wx')['qywx'])) {
            $url = "https://api.weixin.qq.com/cgi-bin/media/get?access_token={$accessToken}&media_id={$mediaId}";
        } else {
            $url = "https://qyapi.weixin.qq.com/cgi-bin/media/get?access_token={$accessToken}&media_id={$mediaId}";
        }

        $ch = curl_init($url);
        curl_setopt($ch, CURLOPT_HEADER, 0);    
        curl_setopt($ch, CURLOPT_NOBODY, 0);    //只取body头
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
        curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
        $package = curl_exec($ch);
        $httpinfo = curl_getinfo($ch);
        curl_close($ch);
        $result = json_decode($package, true);
        if(isset($result['errcode'])) throw new Exception('服务器错误：' . $result['errmsg']);
        $fileInfo = array_merge(array('header' => $httpinfo), array('body' => $package));

        return $fileInfo;
    }

    // 统一下单接口
    public function unifiedorder($body, $tradeNo, $total, $notifyUrl, $tradeType, $openid){
        $url = "https://api.mch.weixin.qq.com/pay/unifiedorder";
        $data['appid'] = $this->appid;
        $data['mch_id'] = $this->payMerchantId;
        $data['nonce_str'] = (string)random_str(32);
        $data['body'] = $body;
        $data['out_trade_no'] = $tradeNo;
        $data['total_fee'] = $total;
        $data['spbill_create_ip'] = "192.168.1.1";
        $data['notify_url'] = $notifyUrl;
        $data['trade_type'] = $tradeType;
        $data['openid'] = $openid;
        ksort($data);
        // 签名
        foreach($data as $k => $v) {
            $tdata[$k] = $k. "=". $v;
        }
        $stringA = implode("&", $tdata). "&key=". $this->payKey;
        $data['sign'] = strtoupper(md5($stringA));

        $xml = $this->to_xml($data);
        $result = $this->from_xml($this->post_data($url, $xml));
        // var_export($result);exit;
        return $result;
    }
    // 获取网页支付API参数
    public function get_webpay_param($prepayId){
        $data['appId'] = $this->appid;
        $data['timeStamp'] = '' . time(); // 苹果需为字符串
        $data['nonceStr'] = (string)random_str(32);
        $data['package'] = 'prepay_id='. $prepayId;
        $data['signType'] = 'MD5';
        ksort($data);
        // 签名
        foreach($data as $k => $v) {
            $tdata[$k] = $k. "=". $v;
        }
        $stringA = implode("&", $tdata). "&key=" . $this->payKey;
        $data['paySign'] = strtoupper(md5($stringA));

        return json_encode($data, JSON_UNESCAPED_UNICODE);
    }
    // 获取全部粉丝
	public function get_all_fans(){
		$accessToken = $this->get_access_token();
		$url = "https://api.weixin.qq.com/cgi-bin/user/get?access_token={$accessToken}&next_openid=";
		$result = json_decode(file_get_contents($url), true);
		//抛错
		if(isset($result['errcode'])) throw new Exception($result['errmsg']);
		//遍历openid
		foreach($result['data']['openid'] as $k => $v) {
			$url = "https://api.weixin.qq.com/cgi-bin/user/info?access_token={$accessToken}&openid={$v}&lang=zh_CN";
			$result = json_decode(file_get_contents($url), true);
			//抛错
			if(isset($result['errcode'])) throw new Exception($result['errmsg']);
			if($result['subscribe'] == 1) {
				//检查是否存在用户信息
				//$query = $this->base->db->query("SELECT * FROM `ci_fans` WHERE `openid`='{$v}'");
				//$fansInfo = $query->row_array();
				//去除不需要的字段
                $result['nickname'] = urlencode($result['nickname']);
				unset($result['tagid_list']);
				unset($result['subscribe']);
				unset($result['language']);
				unset($result['subscribe_time']);
				unset($result['remark']);
				unset($result['groupid']);
				//重新插入粉丝信息
                $this->base->db->insert('ci_fans', $result);
                /*
				if($fansInfo) {
					$this->base->db->update('ci_fans', $result, "id='{$fansInfo['id']}'");
				} else {
					$this->base->db->insert('ci_fans', $result);
				}
                */
			}
		}
    }
    // 发送模板消息
    public function send_template_msg($templateId, $touser, $data, $url){
        if($touser == '') return;

        $postData['touser'] = $touser;
        $postData['template_id'] = $templateId;
        // // 将http替换成https
        // $postUrl = $url ? $url : web_url('index', 'home');
        // if(strpos($postUrl, "ygbaobao.com") !== FALSE && IS_PRODUCT) {
        //     $oldArray = array("http://", urlencode("http://"));
        //     $newArray = array("https://", urlencode("https://"));
        //     $postData['url'] = str_replace($oldArray, $newArray, $postUrl);
        // } else {
        //     $postData['url'] = $postUrl;
        // }
        $postData['url'] = $url;
        $postData['data'] = $data;
        //提交数据
    	$accessToken = $this->get_access_token($this->appid, $this->appsecret);
        $url = "https://api.weixin.qq.com/cgi-bin/message/template/send?access_token={$accessToken}";
        $result = json_decode($this->post_data($url, $postData, true), true);
        
        return $result;
    }
    // post请求
    private function post_data($url, $data, $postJson = false){
        if($postJson) {
            $data = json_encode($data, JSON_UNESCAPED_UNICODE);
        }
        $curl = curl_init();
        //设置抓取的url
        curl_setopt($curl, CURLOPT_URL, $url);
        //设置头文件的信息作为数据流输出
        // curl_setopt($curl, CURLOPT_HEADER, 1);
        //设置获取的信息以文件流的形式返回，而不是直接输出。
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
        //设置post方式提交
        curl_setopt($curl, CURLOPT_POST, 1);
        curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, false); // 访问https，不验证证书下同
        curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, false);
        curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
        if($postJson) {
            curl_setopt($curl, CURLOPT_HTTPHEADER, array(
                'Content-Type: application/json',
                'Content-Length: ' . strlen($data))
            );
        }

        //执行命令
        $data = curl_exec($curl);
        //关闭URL请求
        curl_close($curl);
        return $data;
    }

	/**
	 * 输出xml字符
	 * @throws WxPayException
	**/
	private function to_xml($arr) {
		if(!is_array($arr) || count($arr) <= 0)
		{
    		throw new Exception("数组数据异常！");
    	}
    	
    	$xml = "<xml>";
    	foreach ($arr as $key=>$val)
    	{
    		if (is_numeric($val)){
    			$xml.="<".$key.">".$val."</".$key.">";
    		}else{
    			$xml.="<".$key."><![CDATA[".$val."]]></".$key.">";
    		}
        }
        $xml.="</xml>";
        return $xml; 
	}

    /**
     * 将xml转为array
     * @param string $xml
     * @throws WxPayException
     */
	private function from_xml($xml) {	
		if(!$xml){
			throw new Exception("xml数据异常！");
		}
        //将XML转为array
        //禁止引用外部xml实体
        libxml_disable_entity_loader(true);
        $arr = json_decode(json_encode(simplexml_load_string($xml, 'SimpleXMLElement', LIBXML_NOCDATA)), true);
		return $arr;
	}
}